#include <iostream>

#include "base/Logging.h"
#include "net/UsageEnvironment.h"
#include "base/ThreadPool.h"
#include "net/EventScheduler.h"
#include "net/Event.h"
#include "net/RtspServer.h"
#include "net/MediaSession.h"
#include "net/InetAddress.h"
#include "net/H264FileMediaSource.h"
#include "net/H264RtpSink.h"

int main(int argc, char* argv[])
{
    if(argc !=  2)
    {
        std::cout<<"Usage: "<<argv[0]<<" <h264 file>"<<std::endl;
        return -1;
    }

    //Logger::setLogFile("xxx.log");
    Logger::setLogLevel(Logger::LogDebug);

    //创建调度器scheduler，下面的对象在创建时生成

    //mWakeupFd 为新建的eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
    //POLLER_SELECT 模式

    //mPoller = SelectPoller::createNew(); 
    //这个操作返回一个SelectPoller对象mPoller
    //mPoller的set_fd全部被清空


    //mTimerManager = TimerManager::createNew(mPoller);
    //调用 timerfd_create 创建 timerFd
    //timerFd的clockid为CLOCK_MONOTONIC 
    //                  从系统启动这一刻起开始计时,不受系统时间被用户改变的影响
    //         flags为TFD_NONBLOCK | TFD_CLOEXEC
    //                  (非阻塞模式)
    //                 （表示当程序执行exec函数时本fd将被系统自动关闭,表示不传递）
    //

    //mWakeIOEvent = IOEvent::createNew(mWakeupFd, this);
    //创建IOEvent的对象mWakeIOEvent
    //mFd = mWakeupFd
    //mArg = scheduler

    //mWakeIOEvent->setReadCallback(handleReadCallback);
    //展开成mWakeIOEvent->mReadCallback = EventScheduler::handleReadCallback
    //这个回调 调用 (EventScheduler*)arg->handleRead（）
    //就是一直读取mWakeupFd，大于0跳出。构造函数初始化时mWakeupFd(fd)
    //fd又是EventScheduler::createNew时创建的eventfd


    //mWakeIOEvent->enableReadHandling();
    //展开得mWakeIOEvent->mEvent |= EVENT_READ

    //mPoller->addIOEvent(mWakeIOEvent);
    //FD_SET(fd, &mReadSet)，其中fd为EventScheduler::createNew时创建的eventfd

    //mMutex = Mutex::createNew();
    EventScheduler* scheduler = EventScheduler::createNew(EventScheduler::POLLER_SELECT);


    //创建了两个线程
    ThreadPool* threadPool = ThreadPool::createNew(2);

    //创建env对象，
    //对象中 mScheduler(scheduler)  mThreadPool(threadPool)
    UsageEnvironment* env = UsageEnvironment::createNew(scheduler, threadPool);

    Ipv4Address ipAddr("0.0.0.0", 8554);
    //创建server对象

    //RtspServer是TcpServer的子类，要先执行TcpServer(env, addr)的初始化
    //TcpServer类
    //创建 Acceptor 类对象 mAcceptor ，这个对象实现了监听连接，极其重要
    //mAcceptor->mNewConnectionCallback = server->newConnectionCallback
    //最终调用server->handleNewConnection()


    //RtspServer类
    //RtspServer构造函数创建了 TriggerEvent 类的对象 mTriggerEvent
    //设置mTriggerEvent->mTriggerCallback = server->triggerCallback;

    //具体参考01.05_create_server.md
    
    RtspServer* server = RtspServer::createNew(env, ipAddr);

    //创建MediaSession类的实例session
    //session -> mSessionName = "live"
    //mTracks数组赋值
    //mMulticastRtpInstances等赋值

    //具体参考01.06_create_session.md
    MediaSession* session = MediaSession::createNew("live");
    
    //具体参考01.07_create_mediaSource.md
    MediaSource* mediaSource = H264FileMediaSource::createNew(env, argv[1]);

    //具体参考01.08_create_rtpSink.md
    RtpSink* rtpSink = H264RtpSink::createNew(env, mediaSource);

    //具体参考01.09_addRtpSink.md
    session->addRtpSink(MediaSession::TrackId0, rtpSink);
    //session->startMulticast(); //多播

    //具体参考01.010_addMeidaSession.md
    server->addMeidaSession(session);

    //具体参考01.011_server_start.md
    server->start();

    std::cout<<"Play the media using the URL \""<<server->getUrl(session)<<"\""<<std::endl;
    //具体参考01.012_loop.md
    env->scheduler()->loop();

    return 0;
}